function TS = dlyTS2monthly(dlyTS, ctype)
% dlyTS2monthly  Convert daily TS data to monthly
% dlyTS2monthly(dlyTS, CTYPE) Convert daily data monthly using CTYPE method.
% Valid values:
%    'last'     - Use end of month values (default)
%    'first'    - Use beginning of month values
%    'count'    - Number of non-missing observations per month
%    'return'   - Geometrically convert daily returns to monthly returns
%    'nancorr'  - Matlab corr() function using 'complete' rows parameter
%    'paircorr' - Matlab corr() function using 'pairwise' rows parameter
%    'paircov'  - Matlab nancov() function using 'pairwise' parameter
%    The following Matlab functions are also supported: sum, nansum, mean,
%    nanmean, median, nanmedian, prod, std, nanstd, var, nanvar, min, nanmin,
%    max, nanmax, cov, nancov, corr.
%
% Example:
%    dlyTS2monthly(dlyTS, 'mean')  - Calculate monthly mean
%

if nargin < 2
   ctype = 'last';
end

if dlyTS.dates(1) <= 999999
   error('dlyTS2monthly:notDailyTSstruct', 'input argument is not a daily TS structure')
end

% Function calls of the form fcn(x, dimension)
dim_first_fcn = {'sum' 'nansum' 'mean' 'nanmean' 'median' 'nanmedian' 'prod'};

% Function calls of the form fcn(x, 0, dimension)
dim_second_fcn = {'std' 'nanstd' 'var' 'nanvar'};

% Function calls of the form fcn(x, [], dimension)
maxmin_fcn = {'min' 'nanmin' 'max' 'nanmax'};

% Covariance like functions that don't require special treatment
cov_fcn = {'cov' 'nancov' 'corr'};

% Covariance like functions that require addtional arguments
spec_cov_fcn = {'nancorr' 'paircorr' 'paircov'};

%
% Assign each date to the appropriate month
%

[months junk month_map] = unique(floor(dlyTS.dates / 100));

num_months = length(months);

%
% Build monthly template
%

if ismember(ctype, [cov_fcn spec_cov_fcn])
   TS = buildTS([], dlyTS.header, months, '3D');
else
   TS = buildTS([], dlyTS.header, months);
end

%
% Loop through months and calculate monthly values
%

for i = 1 : num_months
   idx = find(month_map == i);
   if isempty(idx)
      if strcmp('count', ctype)
         TS.data(i, :) = 0;
      end
   else
      x = dlyTS.data(idx, :);
      switch ctype
         case 'first'
            TS.data(i, :) = x(1, :);
         case 'last'
            TS.data(i, :) = x(end, :);
         case 'count'
            TS.data(i, :) = sum(~isnan(x), 1);
         case 'return'
            x(isnan(x)) = 0;
            TS.data(i, :) = prod(1 + x, 1) - 1;
         case dim_first_fcn
            TS.data(i, :) = eval([ctype '(x, 1);']);
         case dim_second_fcn
            TS.data(i, :) = eval([ctype '(x, 0, 1);']);
         case maxmin_fcn
            TS.data(i, :) = eval([ctype '(x, [], 1);']);
         case [cov_fcn spec_cov_fcn]
            if size(x, 1) > 1
               switch ctype
                  case 'nancorr'
                     TS.data(:, :, i) = corr(x, 'rows', 'complete');
                  case 'paircorr'
                     TS.data(:, :, i) = corr(x, 'rows', 'pairwise');
                  case 'paircov'
                     TS.data(:, :, i) = nancov(x, 'pairwise');
                  otherwise
                     TS.data(:, :, i) = eval([ctype '(x);']);
               end
            end
         otherwise
            error('dlyTS2monthly:fcnNotSupported', '%s is not supported', ctype)
      end
   end
end

return
